from prefect import flow, task
from redis import Redis
from rq import Queue
from typing import Dict
import uuid
import logging
from prefect.server.schemas.states import Failed
redis_conn = Redis(host='localhost', port=6379)
workflow_queue = Queue('edu_workflow', connection=redis_conn)

def init_workflow() -> Dict:
    return {
        "workflow_id": str(uuid.uuid4()),
        "status": {
            "html_generated": False,
            "screenshots_done": False,
            "audio_generated": False
        }
    }

@task(name="html-generation", retries=2, retry_delay_seconds=10)
def generate_html_async(json_data):
    from .page_generator import generate_html_pages
    return generate_html_pages(json_data)

@task(name="screenshot-capture", timeout_seconds=300)
def capture_screenshots_async(page_paths):
    from .get_image_list import sync_capture
    return sync_capture(page_paths)

@task(name="tts-generation")
def generate_audio_async(script_text):
    from .tts_service import TTSService
    tts = TTSService()
    return tts.generate(script_text)

@flow(name="full-workflow")
def edu_video_workflow(keyword: str):
    # 初始化流程状态
    workflow_state = init_workflow()
    
    # 并行生成HTML和脚本
    html_task = generate_html_async.submit(workflow_state)
    script_task = generate_script_async.submit(keyword)
    
    # 依赖HTML生成结果执行截图
    screenshot_task = capture_screenshots_async.submit(
        html_task.result()
    )
    
    # 依赖脚本生成结果执行TTS
    audio_task = generate_audio_async.submit(
        script_task.result()
    )
    
    # 最终视频合成
    video_task = generate_video_async.submit(
        timeline=script_task.result(),
        screenshot_dirs=screenshot_task.result(),
        audio_path=audio_task.result()
    )
    
    return {
        "video_path": video_task.result(),
        "workflow_id": workflow_state["workflow_id"]
    }

def log_failure_event(flow, flow_run, state):
    if isinstance(state, Failed):
        error = state.result()
        logging.error(f"Workflow failed: {str(error)}")
        redis_conn.hset(
            f'workflow:{flow_run.id}',
            'status',
            'failed'
        )